package _Banque;

import java.util.*;
import _Exception.IPException;

/**
 * Classe _Banque : constantes fonctionnelles et servitudes
 *
 * @authors V. Pruliere & Q. Salmeron
 */
public abstract class _Banque {

	public final static char NEUTRE = 'N';
	public final static char VERSEMENT = 'V';
	public final static char RETRAIT = 'R';
	public final static char REMUNERATION = 'I';

	/**
	 * Renvoie true ssi l'id passe en parametre est valide
	 */
	public static boolean validiteId(String id) {
		if (id==null || id.equals("")) return false;
		if (id.indexOf(",") != -1) return false;
		return true;
	}

	/**
	 * Renvoie true ssi la date passe en parametre est valide
	 */
	public static boolean validiteDate(String date) {
		if (date == null)
			return false;

		int m = mois(date);
		int j = jour(date);
		int a = annee(date);

		if (a > (annee(dateCourante()) + 1) || a < 1900) {
			return false;
		}
		if ((a == annee(dateCourante())) && m > mois(dateCourante()) || m>12 || m<1) {
			return false;
		}
		if (a == annee(dateCourante()) && m>mois(dateCourante()) && j>jour(dateCourante()) || j>31 || j<1) {
			return false;
		}
		StringTokenizer st = new StringTokenizer(date, "/");
		st.nextToken();
		String s = st.nextToken().toString();
		if (s.length()!=2) {
			return false;
		}
		String s2 = st.nextToken().toString();
		if (s2.length()!=2) {
			return false;
		}
		if ((m<=7 && m%2==0) || (m>7 && m%2==1)) {
			if (j>30)
				return false;
		}
		if (m==2 && isBissextile(annee(date)) && j>29)
			return false;
		if (m==2 && !isBissextile(annee(date)) && j>28)
			return false;
		return true;
	}

	/**
	 * Retourne true ssi l'operation passee en parametre est valide
	 */
	public static boolean operationValide(OperationBancaire op) {
		if (op == null) return false;

		if (op.getType() != 'R' && op.getType() != 'I' && op.getType() != 'V') return false;
		if (op.getIntitule() == null || op.getIntitule().equals("")) return false;
		if (!validiteDate(op.getDate())) return false;
		if (op.getMontant() < 0) return false;

		return true;
	}

	/**
	 * Retourne true ssi la date1 est anterieure a la date2
	 */
	public static boolean anterieur(String date1, String date2) throws IPException {
		if (!validiteDate(date1) || !validiteDate(date2)) throw new IPException();
		if (annee(date1)>annee(date2)) return false;
		else if (annee(date1)<annee(date2)) return true;
		else {
			if (mois(date1)>mois(date2)) return false;
			else if (mois(date1)<mois(date2)) return true;
			else {
				if (jour(date1)>=jour(date2)) return false;
			}
		}
		return true;
	}

	/**
	 * Retourne true ssi la date1 est posterieure a la date2
	 */
	public static boolean posterieur(String date1, String date2) throws IPException {
		return anterieur(date2, date1);
	}


	/***********************************
	 * SERVICE DE GESTION DES DATES
	 **********************************/

	/**
	 * Verifie si une annee est bissextile
	 */
	public static boolean isBissextile(int annee) {
		return (annee%4==0 && (annee%100!=0 || annee%400==0));
	}

	/**
	 * Recupere l'annee d'une date entree
	 */
	public static  int   annee(String date) {
		StringTokenizer st = new StringTokenizer(date, "/");
		String s = st.nextToken().toString();
		int an = 0;
		try {
			an = Integer.parseInt(s);
		}catch (NumberFormatException e) {
			return 0;
		}
		
		return an;
	}

	/**
	 * Recupere le mois d'une date entree
	 */
	public static  int   mois(String date) {
		StringTokenizer st = new StringTokenizer(date, "/");
		st.nextToken();
		String s = st.nextToken().toString();
		int m = 0;
		try {
			m = Integer.parseInt(s);
		}catch (NumberFormatException e) {
			return 0;
		}
		return m;
	}

	/**
	 * Recupere le jour du mois d'une date entree
	 */
	public static int jour(String date) {
		StringTokenizer st = new StringTokenizer(date, "/");
		st.nextToken();
		st.nextToken();
		String s = st.nextToken().toString();
		int j = 0;
		try {
			j = Integer.parseInt(s);
		}catch (NumberFormatException e) {
			return 0;
		}
		return j;
	}

	/**
	 * Retourne le nombre d'annee(s) separant deux dates
	 */
	public static int deltaAnnees(String a1, String a2) {
		int delta = annee(a1) - annee(a2);
		return Math.abs(delta);
	}

	/**
	 * Retourne le nombre de mois separant deux dates
	 */
	public static int deltaMois(String a1, String a2) {
		int total = Math.abs(annee(a1)*12 + mois(a1) - annee(a2)*12 - mois(a2));
		return total;
	}

	/**
	 * Retourne le jour suivant la date passee en parametre
	 * @throws IPException
	 */
	public static String jourSuivant(String date) throws IPException {
		if(!validiteDate(date))
			throw new IPException();
		String m, a, jplus, mplus, aplus;

		a = "" + Integer.toString(annee(date));
		aplus = "" + Integer.toString(annee(date) + 1);


		if (jour(date) < 9){
			//j = "0" + Integer.toString(jour(date));
			jplus = "0" + Integer.toString(jour(date) + 1);
		}
		else{
			//j = "" + Integer.toString(jour(date));
			jplus = "" + Integer.toString(jour(date) + 1);
		}

		if (mois(date) <= 9){
			m = "0" + Integer.toString(mois(date));
			if (mois(date) == 9) mplus = "" + Integer.toString(mois(date) + 1);
			else mplus = "0" + Integer.toString(mois(date) + 1);
		}
		else{
			m = "" + Integer.toString(mois(date));
			mplus = "" + Integer.toString(mois(date) + 1);
		}

		// dernier jour de l'annee (de decembre)
		if(mois(date) == 12 && jour(date) == 31) return "" + aplus + "/01/01";

		// dernier jour de fevrier
		if(mois(date) == 2){
			if(isBissextile(annee(date)) && jour(date) == 29) return "" + a + "/03/01";
			if(!isBissextile(annee(date)) && jour(date) == 28) return "" + a + "/03/01";
		}

		// dernier jour des autres mois (a 31 ou 30 jours)
		if((mois(date)==1 || mois(date)==3 || mois(date)==5 || mois(date)==7 || mois(date)==8 || mois(date)==10) && jour(date) == 31)
			return "" + a + "/" + mplus + "/01";
		if((mois(date)==4 || mois(date)==6 || mois(date)==9 || mois(date)==11) && jour(date) == 30)
			return "" + a + "/" + mplus + "/01";

		// cas general
		return "" + a + "/" + m + "/" + jplus;
	}

	/**
	 * Retourne le lendemain de la date courante
	 */
	public static String demain() {
		try{
			return jourSuivant(dateCourante());
		} catch (IPException e){return dateCourante();}
	}


	/**
	 * Retourne la date courante
	 */
	public static String dateCourante() {
		GregorianCalendar now = new GregorianCalendar();
		int annee = now.get(Calendar.YEAR);
		int mois = now.get(Calendar.MONTH) + 1;
		int jour = now.get(Calendar.DAY_OF_MONTH);
		String m, j;

		if (mois<=9) m = "0" + mois;
		else m = "" + mois;

		if (jour<=9) j = "0" + jour;
		else j = "" + jour;

		return (annee + "/" + m + "/" + j);
	}

	/**
	 * Retourne la date correspondant au debut du prochain mois
	 */
	public static String debutMoisSuivant(String date) {
		int m = mois(date);
		if (m==12) return (annee(date)+1) + "/01/01";
		if (m<9) return annee(date) + "/0" + (m+1) + "/01";
		return annee(date) + "/" + (m+1) + "/01";
	}

	/**
	 * Retourne la date correspondant au debut de la prochaine annee
	 */
	public static String debutAnneeSuivante(String date) {
		return (annee(date)+1) + "/01/01";
	}

}